package com.cupdata.marathon.component;

import com.cupdata.marathon.common.RedisService;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import static com.cupdata.marathon.config.ConfigConstans.*;

/**
 * 守护线程
 * 实现各中心cluster预获取sentinel中优惠券
 */
@Slf4j
@Component
public class CouponClusterSentinelCheck {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource(name = "redissonSentinel")
    private RedissonClient redissonSentinel;

    @Resource(name = "redissonCluster")
    private RedissonClient redissonCluster;

    @Autowired
    private RedisService redisService;

    // 每2s执行一次
    @Scheduled(cron = "0/1 * * * * ?")
    @SchedulerLock(name = "cluster_sentine_check_lock", lockAtLeastFor = "200", lockAtMostFor = "500")
    public void check() {
        log.info("守护线程开始执行：" + Thread.currentThread().getName());

        // 获取中心的优惠券总数
        RAtomicLong localCouponOneTotal = redissonCluster.getAtomicLong(COUPON_ONE_REMAINS);
        RAtomicLong localCouponTwoTotal = redissonCluster.getAtomicLong(COUPON_TWO_REMAINS);

        RAtomicLong remoteCouponOneTotal = redissonSentinel.getAtomicLong(COUPON_ONE_REMAINS);
        RAtomicLong remoteCouponTwoTotal = redissonSentinel.getAtomicLong(COUPON_TWO_REMAINS);

        if (localCouponOneTotal.get() < LOCAL_MIN_NUM && remoteCouponOneTotal.get() > SENTINEL_MIN_NUM) {
            // 总数小于一万，准备从Sentinel获取一万
            logger.info("本中心拉取券1数量{}成功", FETCH_NUM);
            // Sentinel剩余数大于20000，可以拉取
            localCouponOneTotal.addAndGet(FETCH_NUM);
            remoteCouponOneTotal.addAndGet(-FETCH_NUM);
        }
        if (localCouponTwoTotal.get() < LOCAL_MIN_NUM && remoteCouponTwoTotal.get() > SENTINEL_MIN_NUM) {
            // 总数小于一万，准备从Sentinel获取一万
            logger.info("本中心拉取券2数量{}成功", FETCH_NUM);
            // Sentinel剩余数大于20000，可以拉取
            localCouponTwoTotal.addAndGet(FETCH_NUM);
            remoteCouponTwoTotal.addAndGet(-FETCH_NUM);
        }

        // Sentinel总数小于最小值，且中心的总数小于等于0，通知应用直接读取Sentinel总数
        if (remoteCouponOneTotal.get() < SENTINEL_MIN_NUM && localCouponOneTotal.get() <= 0) {
            redisService.deprecateOneLocalRedis();
        }
        if (remoteCouponTwoTotal.get() < SENTINEL_MIN_NUM && localCouponTwoTotal.get() <= 0) {
            redisService.deprecateTwoLocalRedis();
        }
    }
}
